package com.lixin.web.webSocket.impl;


import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.lixin.entity.GroupChatMessage;
import com.lixin.entity.GroupInfo;
import com.lixin.entity.Messages;
import com.lixin.exception.*;
import com.lixin.model.enums.NotifyEnum;
import com.lixin.model.notify.NotifyRes;
import com.lixin.model.request.JoinGroupRequest;
import com.lixin.model.request.ShareGroupRequest;
import com.lixin.model.response.Response;
import com.lixin.redis.RedisKey;
import com.lixin.redis.RedisUtils;
import com.lixin.redis.StringRedisUtil;
import com.lixin.service.IFriendshipsService;
import com.lixin.service.IGroupChatMessageService;
import com.lixin.service.IGroupInfoService;
import com.lixin.service.IMessagesService;
import com.lixin.web.netty.NettyUtil;
import com.lixin.web.webSocket.ChatManager;
import com.lixin.web.webSocket.NotificationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 * Copyright:   Copyright (c)2023
 * Company:     sci
 *
 * @author: 张李鑫
 * @version: 1.0
 * Create at:   2023-08-06 17:16:17
 * <p>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2023-08-06     张李鑫                     1.0         1.0 Version
 */
@Component("chat")
public class ChatManagerImpl implements ChatManager {

    @Autowired
    private IFriendshipsService friendshipsService;

    @Autowired
    private NotificationManager notificationManager;

    @Autowired
    private IGroupInfoService iGroupInfoService;

    @Autowired
    private StringRedisUtil stringRedisUtil;

    @Autowired
    private IMessagesService iMessagesService;

    @Autowired
    private IGroupChatMessageService iGroupChatMessageService;


    @Override
    public Response<Object> sendMessageToUser(Messages messages) {
        //客户端能够发送消息证明已经是好友了，所以这里要检查的是对于对方而言你是否是他的好友
        if (!friendshipsService.isFriend(NettyUtil.getUserId(), messages.getRecipientId())) {
            //不是好友
            throw new FriendshipNotFoundException();
        }
        messages.setSenderId(NettyUtil.getUserId());
        iMessagesService.save(messages);
        notificationManager.sendNotification(
                NotifyRes.createNotify(NotifyEnum.SendMessageToFriend.getValue(), messages),
                messages.getRecipientId());
        return Response.success();
    }

    @Override
    public Response<Object> deleteGroup(Integer groupId) {
        if (groupId == null) {
            throw new ParamsException();
        }
        if (iGroupInfoService.isAdmin(NettyUtil.getUserId())) {
            throw new UserIsNotAdmin();
        }
        return Response.success(iGroupInfoService.deleteByGroupId(groupId));
    }


    @Override
    public Response<Object> sendGroupMessage(GroupChatMessage groupSendMessageRequest) {
        if (groupSendMessageRequest == null) {
            throw new ParamsException();
        }
        Integer groupId = groupSendMessageRequest.getGroupId();
        if (groupId == null) {
            throw new ParamsException();
        }

        if (!iGroupInfoService.isInGroup(groupId, NettyUtil.getUserId())) {
            throw new GroupNotFindException();
        }
        Set<Object> groupMembers = iGroupInfoService.getGroupMember(groupId);
        groupSendMessageRequest.setSenderId(NettyUtil.getUserId());
        iGroupChatMessageService.save(groupSendMessageRequest);

        groupMembers.stream()
                .filter(memberUserId -> !memberUserId.equals(NettyUtil.getUserId()))
                .forEach(groupMemberId ->
                        notificationManager.sendNotification(
                                NotifyRes.createNotify(
                                        NotifyEnum.GroupMessageNotification.getValue(),
                                        groupSendMessageRequest),
                                (Integer) groupMemberId)
                );
        return Response.success();
    }

    @Override
    public Response<GroupInfo> createGroupChat() {
        return Response.success(iGroupInfoService.createGroup(NettyUtil.getUserId()));
    }

    @Override
    public Response<String> shareGroup(ShareGroupRequest shareGroupRequest) {
        GroupInfo groupInfo = iGroupInfoService.selectById(shareGroupRequest.getGroupId());
        if (groupInfo == null) {
            return Response.error("group is not found");
        }
        //这里不同的人分享都会根据不同的人去生成一个code 主要是为了溯源 来发现用户是通过谁的分享进入群聊的
        String qrCode = stringRedisUtil.get(RedisKey.getKey(RedisKey.CREATE_QR_CODE, NettyUtil.getUserId()));
        if (!StrUtil.isEmpty(qrCode)) {
            //说明这个人创建过
            return Response.success(qrCode);
        }
        qrCode = getQrCode();
        stringRedisUtil.set(RedisKey.getKey(RedisKey.CREATE_QR_CODE, NettyUtil.getUserId()), qrCode, stringRedisUtil.QRCODE_TIMEOUT);
        stringRedisUtil.set(RedisKey.getKey(RedisKey.GROUP_QR_CODE, qrCode), groupInfo.getGroupId().toString(), stringRedisUtil.QRCODE_TIMEOUT);
        return Response.success(qrCode);
    }


    /**
     * 理论上这里是需要返回qrcode去返回的 这里只是自己的练习项目 所以暂时用uuid代替。
     * 忽略扫码解析qrcode这一步
     *
     * @return
     */
    private String getQrCode() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString();
    }

    /**
     * 二维码场景或者链接分享的场景？
     * 本质是解析二维码携带的参数传递到后端来 如果拿到了二维码默认是被邀请的成员
     *
     * @param joinGroupRequest
     * @return
     */
    @Override
    public Response<Object> joinGroup(JoinGroupRequest joinGroupRequest) {
        //不对外暴露主键信息
        String groupId = stringRedisUtil.get(RedisKey.getKey(RedisKey.GROUP_QR_CODE, joinGroupRequest.getQrCode()));
        if (StrUtil.isEmpty(groupId)) {
            throw new QRCodeExpiredException();
        }
        iGroupInfoService.joinGroup(NettyUtil.getUserId(), Integer.parseInt(groupId));
        return Response.success();
    }


}
